package com.ticket.system.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Splitter;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.ticket.common.constant.CacheConstants;
import com.ticket.common.constant.PerformConstants;
import com.ticket.common.core.domain.AjaxResult;
import com.ticket.common.core.redis.RedisCache;
import com.ticket.common.exception.ServiceException;
import com.ticket.common.utils.DateUtils;
import com.ticket.common.utils.StringUtils;
import com.ticket.system.domain.TYanchuReservedTicket;
import com.ticket.system.domain.YanchuHallArea;
import com.ticket.system.domain.YanchuSeat;
import com.ticket.system.domain.YanchuSession;
import com.ticket.system.domain.vo.PriceSeatVo;
import com.ticket.system.domain.vo.SeatCompareVo;
import com.ticket.system.domain.vo.SeatImportVo;
import com.ticket.system.domain.vo.SeatVo;
import com.ticket.system.mapper.YanchuHallAreaMapper;
import com.ticket.system.mapper.YanchuSeatMapper;
import com.ticket.system.mapper.YanchuSessionMapper;
import com.ticket.system.service.ITYanchuReservedTicketService;
import com.ticket.system.service.IYanchuSeatService;
import com.ticket.system.service.IYanchuTicketPriceService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 场次座位Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-09-26
 */
@Service
public class YanchuSeatServiceImpl implements IYanchuSeatService 
{
    private static final Logger logger = LoggerFactory.getLogger(YanchuSeatServiceImpl.class);
    @Autowired
    private YanchuSeatMapper yanchuSeatMapper;

    @Autowired
    private YanchuHallAreaMapper yanchuHallAreaMapper;

    @Autowired
    private IYanchuTicketPriceService yanchuTicketPriceService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private YanchuSessionMapper yanchuSessionMapper;

    @Autowired
    private ITYanchuReservedTicketService iTYanchuReservedTicketService;

    @Value("${tempUrl}")
    private String tempUrl;
    /**
     * 查询场次座位
     * 
     * @param id 场次座位主键
     * @return 场次座位
     */
    @Override
    public YanchuSeat selectYanchuSeatById(Long id)
    {
        return yanchuSeatMapper.selectYanchuSeatById(id);
    }

    /**
     * 查询场次座位列表
     * 
     * @param yanchuSeat 场次座位
     * @return 场次座位
     */
    @Override
    public List<YanchuSeat> selectYanchuSeatList(YanchuSeat yanchuSeat)
    {
        return yanchuSeatMapper.selectYanchuSeatList(yanchuSeat);
    }

    /**
     * 查询座位信息
     * @param sessionId
     * @return
     */
    @Override
    public List<SeatVo> selectSeatVoList(Long sessionId){
        return yanchuSeatMapper.selectSeatVoList(sessionId);
    }
    /**
     * 查询座位信息
     * @param sessionId
     * @return
     */
    @Override
    public List<SeatCompareVo> selectResSeatVoList(Long sessionId){
        return yanchuSeatMapper.selectResSeatVoList(sessionId);
    }

    /**
     * 解除预留
     * @param sessionId
     * @param seatVos 新预留列表
     * @return
     */
    @Override
    public void unBindRes(Long sessionId,List<SeatCompareVo> seatVos){
        logger.info("unBindRes:{} seatVos:{}",sessionId,JSONObject.toJSONString(seatVos));
        if(CollectionUtils.isEmpty(seatVos)){
            yanchuSeatMapper.batchSeatOpen(sessionId,null);
        }else{
            //当前预留列表
            List<SeatCompareVo> curVos = selectResSeatVoList(sessionId);
            if(CollectionUtils.isEmpty(curVos)){
                yanchuSeatMapper.batchOpenSeat(sessionId,seatVos);
            }else{
                List<SeatCompareVo> seatVosAdd = (List<SeatCompareVo>)CollectionUtils.subtract(seatVos,curVos);
                List<SeatCompareVo> seatVosRemove = (List<SeatCompareVo>)CollectionUtils.subtract(curVos,seatVos);

                logger.info("unBindRescurVos:{} seatVosAdd:{} seatVosRemove:{}",sessionId,JSONObject.toJSONString(seatVosAdd),
                        JSONObject.toJSONString(seatVosRemove));
                //解除预留
                if(CollectionUtils.isEmpty(seatVosRemove)){
                    yanchuSeatMapper.batchSeatOpen(sessionId,curVos);
                }
                //新增预留
                if(CollectionUtils.isNotEmpty(seatVosAdd)){
                    yanchuSeatMapper.batchLeaveSeat(sessionId,seatVosAdd);
                }
            }
        }
    }
    /**
     * 查询座位信息
     * @param sessionId
     * @return
     */
    @Override
    public YanchuSession selectSessionVo(Long sessionId){
        return yanchuSessionMapper.selectSessionDetailById(sessionId);
    }

    /**
     * 查询座位信息
     * @param sessionId
     * @return
     */
    @Override
    public List<SeatVo> selectSeatVoExportList(Long sessionId){
        return yanchuSeatMapper.selectSeatVoExportList(sessionId);
    }


    @Override
    public Long selectCountSeatList(Long sessionId){
        return yanchuSeatMapper.selectCountSeatList(sessionId);
    }

    /**
     * 新增场次座位
     * 
     * @param yanchuSeat 场次座位
     * @return 结果
     */
    @Override
    public int insertYanchuSeat(YanchuSeat yanchuSeat)
    {
        yanchuSeat.setCreateTime(DateUtils.getNowDate());
        return yanchuSeatMapper.insertYanchuSeat(yanchuSeat);
    }

    /**
     * 停售重新发布
     * @param yanchuSession
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int reservedYanchuSeat(YanchuSession yanchuSession){
        logger.info("reservedYanchuSeat sessionId:{}",yanchuSession.getId());
        Table<String,String,Long> tables = generateResTable(yanchuSession.getId());//预留座转table
        YanchuSeat yanchuSeat = new YanchuSeat();
        yanchuSeat.setSessionId(yanchuSession.getId());
        List<YanchuSeat> listSeat = yanchuSeatMapper.selectOpenSeatList(yanchuSeat);
        if(CollectionUtils.isEmpty(listSeat)){
            return 1;
        }
        List<YanchuSeat> cancelYuliu = Lists.newArrayList();
        List<YanchuSeat> newYuliu = Lists.newArrayList();
        Long resId = null;
        for(YanchuSeat yanchuSeatDb:listSeat){
            if(yanchuSeatDb.getStatus() == PerformConstants.TICKET_SEAT_OPEN){//出售状态
                resId = tables.get(yanchuSeatDb.getAreaId()+":"+yanchuSeatDb.getRowNumber(),yanchuSeatDb.getxPos()+"");
                if(null != resId ){//转预留
                    yanchuSeatDb.setReservedId(resId);
                    newYuliu.add(yanchuSeatDb);
                }
            }else if(yanchuSeatDb.getStatus() == PerformConstants.TICKET_SEAT_NOT_OPEN){//预留状态
                resId = tables.get(yanchuSeatDb.getAreaId()+":"+yanchuSeatDb.getRowNumber(),yanchuSeatDb.getxPos()+"");
                if(null == resId){//转出售
                    cancelYuliu.add(yanchuSeatDb);
                }else if(!resId.equals(yanchuSeatDb.getReservedId())){
                    yanchuSeatDb.setReservedId(resId);
                    newYuliu.add(yanchuSeatDb);
                }
            }
        }
        int count = 0;
        if(CollectionUtils.isNotEmpty(cancelYuliu)){
            logger.info("cancelYuliu:{}",JSONObject.toJSONString(cancelYuliu));
            //更新为出售
            count = yanchuSeatMapper.batchUpdateSeatOpen(cancelYuliu,PerformConstants.TICKET_SEAT_OPEN,PerformConstants.TICKET_SEAT_NOT_OPEN);
            if(count != cancelYuliu.size()){
                throw new ServiceException("更新座位出售状态失败！");
            }
            yanchuSessionMapper.updateReservNum(-cancelYuliu.size(),yanchuSession.getId());
        }
        if(CollectionUtils.isNotEmpty(newYuliu)){
            logger.info("newYuliu:{}",JSONObject.toJSONString(newYuliu));
            for(YanchuSeat seat:newYuliu){
                //更新为预留
                yanchuSeatMapper.batchUpdateSeatNotOpen(seat.getReservedId(),PerformConstants.TICKET_SEAT_NOT_OPEN,seat.getId());
            }

            yanchuSessionMapper.updateReservNum(newYuliu.size(),yanchuSession.getId());
        }
        //放缓存
        generateTicket(yanchuSession);
        return count;
    }

    /**
     * 初始化场次座位
     * @param yanchuSession
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int initYanchuSeat(YanchuSession yanchuSession){
        logger.info("initYanchuSeat sessionId:{}",yanchuSession.getId());
        Long countSeat = selectCountSeatList(yanchuSession.getId());
        if(countSeat > 0){
            throw new ServiceException("存在座位数据，发布失败！");
        }

        List<YanchuHallArea> hallList = yanchuHallAreaMapper.selectHallAreaList(yanchuSession.getHallId());
        if(CollectionUtils.isEmpty(hallList)){
            return -1;
        }
        List<YanchuSeat> seatsList = Lists.newArrayList();
        JSONArray jsonArray = null,seatsJsonArray = null;
        JSONObject jsonObject = null,seatJsonObject = null;
        String seats = null;
        Integer row = null,resveredCount = 0,seatCount = 0;
        PriceSeatVo priceSeatVo = null;
        YanchuSeat seat = null;
        StringBuilder sb = null;
        BigDecimal totalMoney = BigDecimal.ZERO;
        Table<String, String, PriceSeatVo> tabs = yanchuTicketPriceService.selectPriceList(yanchuSession.getId());
        logger.info("tabs:{}",tabs);
        Table<String,String,Long> resTable = generateResTable(yanchuSession.getId());
        logger.info("resTable:{}",resTable);
        Long resId = null;
        Integer rowNo = null;
        //循环区域
        for(YanchuHallArea area:hallList){
            if(StringUtils.isEmpty(area.getSeatState())){
                continue;
            }
            jsonArray = JSONArray.parseArray(area.getSeatState());//[{"row":1,"seats":[{"col":8,"seatNo":29},{"col":9,"seatNo":27}]}]
            logger.info("area.getSeatState()",area.getSeatState());
            for(int i=0;i<jsonArray.size();i++){
                jsonObject = jsonArray.getJSONObject(i);
                seatsJsonArray = jsonObject.getJSONArray("seats");
                row = jsonObject.getInteger("row");
                if(null == seatsJsonArray || seatsJsonArray.size()==0 || null == row){
                    logger.info("获取座位信息失败:{} {}",seats,row);
                    continue;
                }

                for(int j=0;j<seatsJsonArray.size();j++){
                    seatJsonObject = seatsJsonArray.getJSONObject(j);
                    priceSeatVo = tabs.get(area.getId()+"_"+row,seatJsonObject.getString("col"));

                    logger.info("tabs.get areaId:{} col:{} {}",area.getId()+"_"+row,seatJsonObject.getString("col"),null==priceSeatVo?null:priceSeatVo.getPriceId());
                    seat = new YanchuSeat();
                    seat.setHallId(yanchuSession.getHallId());
                    seat.setAreaId(area.getId());
                    seat.setSessionId(yanchuSession.getId());
                    seat.setSeatNumber(seatJsonObject.getInteger("seatNo"));
                    if(PerformConstants.TABLE_AREAS.contains(area.getId())){//桌号票
                        seat.setRowNumber(row);
                        seat.setShowNumber(seatJsonObject.getInteger("tab")+"桌"+seatJsonObject.getInteger("seatNo")+"座");
                    }else if(PerformConstants.COMB_AREAS.contains(area.getId()) || PerformConstants.TAB_AREAS.contains(area.getId())){//包间票
                        seat.setRowNumber(row);
                        seat.setShowNumber(seatJsonObject.getString("tab")+seatJsonObject.getInteger("seatNo")+"座");
                    }else if(PerformConstants.ROWNO_AREAS.contains(area.getId())){//排号票
                        seat.setRowNumber(row);
                        rowNo = seatJsonObject.getInteger("rowNo");
                        seat.setShowNumber((null == rowNo?row:rowNo)+"排"+seatJsonObject.getInteger("seatNo")+"座");
                    }else{
                        seat.setRowNumber(row);
                        seat.setShowNumber(row+"排"+seatJsonObject.getInteger("seatNo")+"座");
                    }
                    if(null == priceSeatVo){
                        seat.setStatus(PerformConstants.TICKET_SEAT_INIT);
                    }else{
                        seat.setxPos(priceSeatVo.getxPos());
                        sb = new StringBuilder(yanchuSession.getId()+"");
                        //票号
                        //sb.append(getSessionSerialNo(yanchuSession.getId())).append(StringUtils.padl(RandomUtil.randomInt(1,999)+"",3,'0'));
                        sb.append(StringUtils.padl(row+"",2,'0')).append(StringUtils.padl(priceSeatVo.getxPos()+"",2,'0')).append(getSessionSerialNo(yanchuSession.getId()));
                        seat.setTicket(sb.toString());

                        seat.setMoney(priceSeatVo.getPrice());
                        totalMoney = totalMoney.add(priceSeatVo.getPrice());
                        seatCount += 1;
                        seat.setPriceId(priceSeatVo.getPriceId());
                        resId = resTable.get(area.getId()+":"+row,seatJsonObject.getString("col"));

                        if(null != resId){//预留座不外放
                            logger.info("res key:{} kkey:{} resId:{}",area.getId()+":"+row,seatJsonObject.getString("col"),resId);
                            seat.setStatus(PerformConstants.TICKET_SEAT_NOT_OPEN);
                            seat.setReservedId(resId);
                            resveredCount+=1;
                        }else{
                            seat.setStatus(PerformConstants.TICKET_SEAT_OPEN);
                        }
                    }
                    seatsList.add(seat);
                }
            }
        }
        if(CollectionUtils.isEmpty(seatsList)){
            throw new ServiceException("座位信息查询失败！");
        }
        int count = yanchuSeatMapper.insertBatchSeat(seatsList);
        if(count == 0){
            throw new ServiceException("场次发布失败！");
        }
        //放缓存
        generateTicket(yanchuSession);
        //更新总座位数
        yanchuSessionMapper.updateTotalMoney(yanchuSession.getId(),seatCount,totalMoney,resveredCount);
        return count;
    }

    /**
     * 预留座转table
     * @param sessionId
     * @return
     */
    private Table<String,String,Long> generateResTable(Long sessionId){
        JSONArray jsonArray = null;
        JSONObject jsonObject = null;
        String seats = null;
        List<String> seatList = null;
        List<String> colList = null;
        Integer row = null;
        TYanchuReservedTicket tYanchuReservedTicket = new TYanchuReservedTicket();
        tYanchuReservedTicket.setSessionId(sessionId);
        List<TYanchuReservedTicket> listReserved = iTYanchuReservedTicketService.selectTYanchuReservedTicketList(tYanchuReservedTicket);
        Table<String,String,Long> tables = HashBasedTable.create();
        if(CollectionUtils.isEmpty(listReserved)){
            return tables;
        }
        Integer areaId = null;
        String cols = null;
        JSONArray jsonSeatArray = null;
        for(TYanchuReservedTicket ticketRes : listReserved){
            if(StringUtils.isEmpty(ticketRes.getSeats())){
                continue;
            }
            jsonArray = JSONArray.parseArray(ticketRes.getSeats());
            for(int i=0;i<jsonArray.size();i++){
                areaId = jsonArray.getJSONObject(i).getInteger("areaId");
                seats = jsonArray.getJSONObject(i).getString("seats");
                jsonSeatArray = JSONArray.parseArray(seats);
                for(int j=0;j<jsonSeatArray.size();j++){
                    jsonObject = jsonSeatArray.getJSONObject(j);
                    row = jsonObject.getInteger("row");
                    cols = jsonObject.getString("col");
                    colList = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(cols);
                    for(int k=0;k<colList.size();k++){
                        tables.put(areaId+":"+row,colList.get(k),ticketRes.getResSeatId());//预留座类型编码
                    }
                }
            }
        }
        return tables;
    }

    /**
     * 放缓存
     * @param yanchuSession
     * @return
     */
    private void generateTicket(YanchuSession yanchuSession){
        YanchuSeat yanchuSeat = new YanchuSeat();
        yanchuSeat.setSessionId(yanchuSession.getId());
        List<YanchuSeat> seatList = yanchuSeatMapper.selectYanchuSeatList(yanchuSeat);
        if(CollectionUtils.isEmpty(seatList)){
            return;
        }
        String key = CacheConstants.TICKET_LOCK_KEY+yanchuSession.getId();
        Map<String,YanchuSeat> seatMap = Maps.newHashMap();
        for(YanchuSeat seat:seatList){
            String hKey = seat.getAreaId()+"-"+seat.getRowNumber()+"-"+seat.getxPos();
            seatMap.put(hKey,seat);
        }
        redisCache.mMapSet(key,seatMap,180, TimeUnit.DAYS);
    }

    @Override
    public void refreshTicketCache(List<YanchuSeat> yanchuSeats){
        if(CollectionUtils.isEmpty(yanchuSeats)){
            return;
        }
        String key = CacheConstants.TICKET_LOCK_KEY+yanchuSeats.get(0).getSessionId();
        for(YanchuSeat seat:yanchuSeats){
            String hKey = seat.getAreaId()+"-"+seat.getRowNumber()+"-"+seat.getxPos();
            redisCache.setCacheMapValue(key,hKey,seat);
        }
    }

    @Override
    public void refreshTicketList(List<YanchuSeat> seatList,Long sessionId) {
        if (CollectionUtils.isEmpty(seatList)) {
            return;
        }
        if(null == sessionId){
            sessionId = seatList.get(0).getSessionId();
        }
        Map<String, YanchuSeat> map = Maps.newHashMap();
        String keySession = CacheConstants.TICKET_LOCK_KEY + sessionId;
        String hKey = null;
        for (YanchuSeat seatVo : seatList) {
            hKey = seatVo.getAreaId() + "-" + seatVo.getRowNumber() + "-" + seatVo.getxPos();
            map.put(hKey, seatVo);
        }
        logger.info("refreshTicketList sessionId:{} seatList:{}",sessionId,JSONObject.toJSONString(seatList));
        redisCache.mMapSet(keySession, map, 180, TimeUnit.DAYS);
    }

    /**
     * 删除售票缓存
     * @param sessionId
     */
    public void cancelTicketCache(Long sessionId){
        String key = CacheConstants.TICKET_LOCK_KEY+sessionId;
        redisCache.deleteObject(key);
    }

    /**
     * 抢票
     * @param seatVos
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<YanchuSeat> grabTicket(Long sessionId,Long userId,List<SeatVo> seatVos,Long orderId){
        logger.info("grabTicket sessionId:{} userId:{} orderId:{} seatVos:{}",sessionId,userId,orderId,JSONObject.toJSONString(seatVos));
        List<Object> keys = Lists.newArrayList();
        String hKey = null;
        for(SeatVo seatVo:seatVos){
            hKey = seatVo.getAreaId()+"-"+seatVo.getRowNumber()+"-"+seatVo.getxPos();
            keys.add(hKey);
        }
        String keySession = CacheConstants.TICKET_LOCK_KEY+sessionId;
        List<YanchuSeat> seatList = redisCache.getMultiCacheMapValue(keySession,keys);

        if(CollectionUtils.isEmpty(seatList) || seatList.size() != seatVos.size()){
            throw new ServiceException("手速太慢了!您选的座位已被抢占!");
        }
        YanchuSeat dbSeat = null;
        for(YanchuSeat seat:seatList){
            if(null == seat || !seat.getStatus().equals(PerformConstants.TICKET_SEAT_OPEN)){
                logger.info("座位获取失败:{}",seat);
                if(null == seat){
                    throw new ServiceException("手速太慢了!您选的座位已被抢占!");
                }
                dbSeat = yanchuSeatMapper.selectYanchuSeatById(seat.getId());
                logger.info("dbSeat:{}",dbSeat);
                if(null != dbSeat && dbSeat.getStatus().equals(PerformConstants.TICKET_SEAT_OPEN)){
                    seat.setStatus(PerformConstants.TICKET_SEAT_WAIT_PAY);
                }else{
                    throw new ServiceException("手速太慢了!您选的座位已被抢占!");
                }
            }else{
                seat.setStatus(PerformConstants.TICKET_SEAT_WAIT_PAY);
            }
        }
        int count = yanchuSeatMapper.grabBatchSeat(userId,seatList,PerformConstants.TICKET_SEAT_WAIT_PAY,
                PerformConstants.TICKET_SEAT_OPEN,orderId);
        if(count != seatList.size()){
            throw new ServiceException("手速太慢了!您选的座位已被抢占!");
        }

        return seatList;
    }

    /**
     * 修改场次座位
     * 
     * @param seatVos 场次座位
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<YanchuSeat> grabNoPayTicket(Long sessionId,Long userId,List<SeatVo> seatVos,Long orderId){
        logger.info("grabNoPayTicket sessionId:{} userId:{} orderId:{} seatVos:{}",sessionId,userId,orderId,JSONObject.toJSONString(seatVos));
        List<Object> keys = Lists.newArrayList();
        String hKey = null;
        for(SeatVo seatVo:seatVos){
            hKey = seatVo.getAreaId()+"-"+seatVo.getRowNumber()+"-"+seatVo.getxPos();
            keys.add(hKey);
        }
        String keySession = CacheConstants.TICKET_LOCK_KEY+sessionId;
        List<YanchuSeat> seatList = redisCache.getMultiCacheMapValue(keySession,keys);

        if(CollectionUtils.isEmpty(seatList) || seatList.size() != seatVos.size()){
            throw new ServiceException("缓存获取座位失败!");
        }
        for(YanchuSeat seat:seatList){
            if(null == seat || !seat.getStatus().equals(PerformConstants.TICKET_SEAT_OPEN)){
                throw new ServiceException("座位获取失败!");
            }else{
                seat.setStatus(PerformConstants.TICKET_SEAT_PAY);
            }
        }
        int count = yanchuSeatMapper.grabBatchSeat(userId,seatList,PerformConstants.TICKET_SEAT_PAY,
                PerformConstants.TICKET_SEAT_OPEN,orderId);
        if(count != seatList.size()){
            throw new ServiceException("座位更新状态失败!");
        }

        return seatList;
    }

    /**
     * 修改场次座位
     *
     * @param seatVos 场次座位
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult grabBackendTicket(Long sessionId,Long userId,List<SeatVo> seatVos,Long orderId){
        logger.info("grabBackendTicket sessionId:{} userId:{} orderId:{} seatVos:{}",sessionId,userId,orderId,JSONObject.toJSONString(seatVos));
        List<Object> keys = Lists.newArrayList();
        String hKey = null;
        Map<String,SeatVo> vosMap = Maps.newHashMap();
        for(SeatVo seatVo:seatVos){
            hKey = seatVo.getAreaId()+"-"+seatVo.getRowNumber()+"-"+seatVo.getxPos();
            vosMap.put(hKey,seatVo);
            keys.add(hKey);
        }
        String keySession = CacheConstants.TICKET_LOCK_KEY+sessionId;
        List<YanchuSeat> seatList = redisCache.getMultiCacheMapValue(keySession,keys);

//        if(CollectionUtils.isEmpty(seatList) || seatList.size() != seatVos.size()){
//            throw new ServiceException("缓存获取座位失败!");
//        }

        AjaxResult resultAjax = AjaxResult.success();
        SeatVo seatVo = null;
        YanchuSeat seat = null;
        List<SeatVo> errorList = Lists.newArrayList();
        for(int i=seatList.size()-1;i>=0;i--){
            seat = seatList.get(i);
            if(null == seat || (!seat.getStatus().equals(PerformConstants.TICKET_SEAT_OPEN) &&
                    !seat.getStatus().equals(PerformConstants.TICKET_SEAT_NOT_OPEN))){
                logger.info("error seat:{}",JSONObject.toJSONString(seat));
                seatList.remove(i);
                hKey = seat.getAreaId()+"-"+seat.getRowNumber()+"-"+seat.getxPos();
                seatVo = vosMap.get(hKey);
                if(null != seatVo){
                    errorList.add(seatVo);
                }
            }else{
                seat.setStatus(PerformConstants.TICKET_SEAT_PAY);
            }
        }

        int count = yanchuSeatMapper.grabBatchSeat(userId,seatList,PerformConstants.TICKET_SEAT_PAY,
                null,orderId);
        if(count != seatList.size()){
            throw new ServiceException("座位更新状态失败!");
        }
        resultAjax.put("errorList",errorList);
        resultAjax.put("seatList",seatList);
        return resultAjax;
    }
    /**
     * 修改场次座位
     * 
     * @param yanchuSeat 场次座位
     * @return 结果
     */
    @Override
    public int updateYanchuSeat(YanchuSeat yanchuSeat)
    {
        yanchuSeat.setUpdateTime(DateUtils.getNowDate());
        return yanchuSeatMapper.updateYanchuSeat(yanchuSeat);
    }

    /**
     * 批量删除场次座位
     * 
     * @param ids 需要删除的场次座位主键
     * @return 结果
     */
    @Override
    public int deleteYanchuSeatByIds(Long[] ids)
    {
        return yanchuSeatMapper.deleteYanchuSeatByIds(ids);
    }

    /**
     * 删除场次座位信息
     * 
     * @param id 场次座位主键
     * @return 结果
     */
    @Override
    public int deleteYanchuSeatById(Long id)
    {
        return yanchuSeatMapper.deleteYanchuSeatById(id);
    }

    /**
     * 导出座位列表  执行
     */
    public void executeExportOrder(List<SeatImportVo> list, HttpServletResponse response){
        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        String templateFileName = tempUrl + "seatListExportTemp.xlsx";
        //String templateFileName = "D:/doc/工作/演出/seatListExportTemp.xlsx";
        String fileName = "后台出票明细批量导入模板.xlsx";
        //String fileName = "D:/doc/工作/演出/" + "导出订单列表" + System.currentTimeMillis() + ".xlsx";
        try {
            SeatImportVo vo = null;
            for(int i=0;i<list.size();i++){
                vo = list.get(i);
                vo.setJsonStr(JSON.toJSONString(vo));
                vo.setIndex(i+1);
            }
            logger.debug("executeExportOrder:{}",JSONObject.toJSONString(list));
            //替换成自己的数据
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            //fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            EasyExcel.write(response.getOutputStream()).withTemplate(templateFileName).sheet().doFill(list);
        } catch (Exception e) {
            logger.error("executeExportOrder",e);
        }
    }

    public List<SeatImportVo> executeImportOrder(MultipartFile file){
        try {
            // 这里 需要指定读用哪个class去读，然后读取第一个sheet 同步读取会自动finish
            List<SeatImportVo> list = EasyExcel.read(file.getInputStream()).headRowNumber(2).head(SeatImportVo.class).sheet().doReadSync();
            JSONObject jsonObj = null;
            String jsonStr = null;
            String idTypeStr = null;
            for (SeatImportVo data : list) {
                jsonStr = data.getJsonStr();
                if(StringUtils.isEmpty(jsonStr)){
                    throw new ServiceException("未获取到json数据，导入失败！");
                }
                idTypeStr = data.getIdType();
                if("身份证".equals(idTypeStr)){
                    data.setIdType(PerformConstants.ID_TYPE_1+"");
                }else if("护照".equals(idTypeStr)){
                    data.setIdType(PerformConstants.ID_TYPE_2+"");
                }else if("港澳台通行证及居住证".equals(idTypeStr)){
                    data.setIdType(PerformConstants.ID_TYPE_3+"");
                }else{
                    data.setIdType(PerformConstants.ID_TYPE_0+"");
                }

                jsonObj = JSONObject.parseObject(jsonStr);
                data.setHallId(jsonObj.getLong("hallId"));
                data.setPriceId(jsonObj.getLong("priceId"));
                data.setPrice(jsonObj.getBigDecimal("price"));
                data.setAreaName(jsonObj.getString("areaName"));
                data.setAreaId(jsonObj.getInteger("areaId"));
                data.setRow(jsonObj.getInteger("row"));
                data.setSetNum(jsonObj.getLong("setNum"));
                data.setTab(jsonObj.getString("tab"));
            }
            return list;
        } catch (Exception e) {
            logger.error("executeExportOrder",e);
            return null;
        }
    }
    /**
     *
     *
     * @param idArea 区域编码
     * @return 结果
     */
    @Override
    public List<YanchuSeat> selectRowListByAreaId(Long idArea){
        return yanchuSeatMapper.selectRowListByAreaId(idArea);
    }
    /**
     * 删除场次座位信息
     *
     * @param rowNumber
     * @return 结果
     */
    @Override
    public List<YanchuSeat> selectSeatListByRowNo(Long rowNumber,Long idArea){
        return yanchuSeatMapper.selectSeatListByRowNo(rowNumber,idArea);
    }

    /**
     * 按场次生成序列号
     * @param sessionId
     * @return
     */
    public String getSessionSerialNo(Long sessionId){
        Long serialNo = redisCache.incr(CacheConstants.TICKETNO_KEY+sessionId);
        return StringUtils.padl(serialNo+"",3,'0');
    }

    /**
     * 删除场次生成序列号
     * @param sessionId
     * @return
     */
    public void delSessionSerialNo(Long sessionId){
        redisCache.deleteObject(CacheConstants.TICKETNO_KEY+sessionId);
    }
}
